home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
dev
/
c
/
ctags.lha
/
ctags-3.0.3
/
fortran.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-02-17
|
23KB
|
983 lines
/*****************************************************************************
* $Id: fortran.c,v 7.4 1998/12/22 03:28:47 darren Exp $
*
* Copyright (c) 1998, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License.
*
* This module contains functions for generating tags for Fortran language
* files.
*****************************************************************************/
/*============================================================================
= Include files
============================================================================*/
#include "general.h"
#include <string.h>
#include <limits.h>
#include <ctype.h> /* to define tolower() */
#include <setjmp.h>
#include "debug.h"
#include "entry.h"
#include "keyword.h"
#include "main.h"
#include "options.h"
#include "parse.h"
#include "read.h"
#include "vstring.h"
/*============================================================================
= Macros
============================================================================*/
#define isType(token,t) (boolean)((token)->type == (t))
#define isKeyword(token,k) (boolean)((token)->keyword == (k))
/*============================================================================
= Data declarations
============================================================================*/
typedef enum eException {
ExceptionNone, ExceptionEOF, ExceptionFixedFormat
} exception_t;
/* Used to designate type of line read in fixed source form.
*/
typedef enum eFortranLineType {
LTYPE_UNDETERMINED,
LTYPE_INVALID,
LTYPE_COMMENT,
LTYPE_CONTINUATION,
LTYPE_EOF,
LTYPE_INITIAL,
LTYPE_SHORT
} lineType;
/* Used to specify type of keyword.
*/
typedef enum eKeywordId {
KEYWORD_NONE,
KEYWORD_assignment,
KEYWORD_block,
KEYWORD_common,
KEYWORD_data,
KEYWORD_end,
KEYWORD_entry,
KEYWORD_function,
KEYWORD_interface,
KEYWORD_module,
KEYWORD_namelist,
KEYWORD_operator,
KEYWORD_program,
KEYWORD_subroutine,
KEYWORD_type
} keywordId;
/* Used to determine whether keyword is valid for the token language and
* what its ID is.
*/
typedef struct sKeywordDesc {
const char *name;
keywordId id;
} keywordDesc;
typedef enum eTokenType {
TOKEN_UNDEFINED,
TOKEN_COMMA,
TOKEN_DECLARATION,
TOKEN_IDENTIFIER,
TOKEN_KEYWORD,
TOKEN_LABEL,
TOKEN_NEWLINE,
TOKEN_NUMERIC,
TOKEN_OPERATOR,
TOKEN_PAREN_CLOSE,
TOKEN_PAREN_OPEN,
TOKEN_STRING
} tokenType;
typedef enum eTagType {
TAG_UNDEFINED,
TAG_BLOCK_DATA,
TAG_COMMON_BLOCK,
TAG_ENTRY_POINT,
TAG_FUNCTION,
TAG_INTERFACE,
TAG_LABEL,
TAG_MODULE,
TAG_NAMELIST,
TAG_PROGRAM,
TAG_SUBROUTINE,
TAG_DERIVED_TYPE,
TAG_VARIABLE,
TAG_COUNT /* must be last */
} tagType;
typedef struct sTokenInfo {
tokenType type;
keywordId keyword;
tagType tag;
vString * string;
unsigned long lineNumber;
fpos_t filePosition;
} tokenInfo;
/*============================================================================
= Data definitions
============================================================================*/
static jmp_buf Exception;
static int Ungetc = '\0';
static unsigned int Column = 0;
static boolean FreeSourceForm = FALSE;
static tokenInfo *Parent = NULL;
static const keywordDesc FortranKeywordTable[] = {
/* keyword keyword ID */
{ "assignment", KEYWORD_assignment },
{ "block", KEYWORD_block },
{ "common", KEYWORD_common },
{ "data", KEYWORD_data },
{ "end", KEYWORD_end },
{ "entry", KEYWORD_entry },
{ "function", KEYWORD_function },
{ "interface", KEYWORD_interface },
{ "module", KEYWORD_module },
{ "namelist", KEYWORD_namelist },
{ "operator", KEYWORD_operator },
{ "program", KEYWORD_program },
{ "subroutine", KEYWORD_subroutine },
{ "type", KEYWORD_type }
};
/*============================================================================
= Function prototypes
============================================================================*/
static void buildFortranKeywordHash __ARGS((void));
static const char *tagName __ARGS((const tagType type));
static int tagLetter __ARGS((const tagType type));
static boolean includeTag __ARGS((const tagType type));
static void copyToken __ARGS((tokenInfo *const dest, const tokenInfo *const src));
static void makeFortranTag __ARGS((const tokenInfo *const token));
static int skipLine __ARGS((void));
static void makeLabelTag __ARGS((vString *const label));
static lineType getLineType __ARGS((void));
static int getFixedFormChar __ARGS((void));
static int getFreeFormChar __ARGS((void));
static int getChar __ARGS((void));
static void ungetChar __ARGS((const int c));
static vString *parseInteger __ARGS((int c));
static vString *parseNumeric __ARGS((int c));
static void parseString __ARGS((vString *const string, const int delimeter));
static void parseIdentifier __ARGS((vString *const string, const int firstChar));
static keywordId analyzeToken __ARGS((vString *const name));
static int skipToChar __ARGS((const int toChar));
static void readToken __ARGS((tokenInfo *const token));
static void setTagType __ARGS((tokenInfo *const token, const tagType type));
static void nameTag __ARGS((tokenInfo *const token, const tagType type));
static void parseParenName __ARGS((tokenInfo *const token));
static void parseInterface __ARGS((tokenInfo *const token));
static void tagSlashName __ARGS((tokenInfo *const token, const tagType type));
static void parseType __ARGS((tokenInfo *const token));
static void parseBlock __ARGS((tokenInfo *const token));
static void parseFile __ARGS((tokenInfo *const token));
static tokenInfo *newToken __ARGS((void));
static void deleteToken __ARGS((tokenInfo *const token));
static void init __ARGS((void));
/*============================================================================
= Function definitions
============================================================================*/
static void buildFortranKeywordHash()
{
const size_t count = sizeof(FortranKeywordTable) /
sizeof(FortranKeywordTable[0]);
size_t i;
for (i = 0 ; i < count ; ++i)
{
const keywordDesc *p = &FortranKeywordTable[i];
addKeyword(p->name, LANG_FORTRAN, (int)p->id);
}
}
/*----------------------------------------------------------------------------
*- Tag generation functions
----------------------------------------------------------------------------*/
static const char *tagName( type )
const tagType type;
{
/* Note that the strings in this array must correspond to the types in
* the tagType enumeration.
*/
static const char *names[] = {
"undefined", "block data", "common", "entry", "function",
"interface", "label", "module", "namelist", "program", "subroutine",
"type", "variable"
};
Assert(sizeof(names)/sizeof(names[0]) == TAG_COUNT);
return names[(int)type];
}
static int tagLetter( type )
const tagType type;
{
/* Note that the characters in this list must correspond to the types in
* the tagType enumeration.
*/
const char *const chars = "?bcefilmnpstv";
Assert(strlen(chars) == TAG_COUNT);
return chars[(int)type];
}
static boolean includeTag( type )
const tagType type;
{
const struct sFortranInclude *const inc = &Option.include.fortran;
boolean include;
switch (type)
{
case TAG_BLOCK_DATA: include = inc->blockData; break;
case TAG_COMMON_BLOCK: include = inc->commonBlocks; break;
case TAG_ENTRY_POINT: include = inc->entryPoints; break;
case TAG_FUNCTION: include = inc->functions; break;
case TAG_INTERFACE: include = inc->interfaces; break;
case TAG_MODULE: include = inc->modules; break;
case TAG_NAMELIST: include = inc->namelists; break;
case TAG_PROGRAM: include = inc->programs; break;
case TAG_SUBROUTINE: include = inc->subroutines; break;
case TAG_DERIVED_TYPE: include = inc->types; break;
case TAG_LABEL: include = (boolean)(inc->labels &&
Option.include.fileScope); break;
default: